{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6641bb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|hide\n",
    "#|default_exp xdg"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7d9eea4",
   "metadata": {},
   "source": [
    "# XDG\n",
    "\n",
    "> XDG Base Directory Specification helpers."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5fd471d",
   "metadata": {},
   "source": [
    "See the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) for more information."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6520e8e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "from fastcore.utils import *"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e92607f",
   "metadata": {},
   "source": [
    "## Overview"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8090f3e5",
   "metadata": {},
   "source": [
    "`xdg_cache_home`, `xdg_config_home`, `xdg_data_home`, and `xdg_state_home`\n",
    "return `pathlib.Path` objects containing the value of the environment variable\n",
    "named `XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, and `XDG_STATE_HOME`\n",
    "respectively, or the default defined in the specification if the environment\n",
    "variable is unset, empty, or contains a relative path rather than absolute\n",
    "path.\n",
    "\n",
    "`xdg_config_dirs` and `xdg_data_dirs` return a list of `pathlib.Path`\n",
    "objects containing the value, split on colons, of the environment\n",
    "variable named `XDG_CONFIG_DIRS` and `XDG_DATA_DIRS` respectively, or the\n",
    "default defined in the specification if the environment variable is\n",
    "unset or empty. Relative paths are ignored, as per the specification.\n",
    "\n",
    "`xdg_runtime_dir` returns a `pathlib.Path` object containing the value of\n",
    "the `XDG_RUNTIME_DIR` environment variable, or `None` if the environment\n",
    "variable is not set, or contains a relative path rather than absolute path."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9b60c79",
   "metadata": {},
   "source": [
    "## Helpers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38ec0a9d",
   "metadata": {},
   "source": [
    "We'll start by defining a context manager that temporarily sets an environment variable to demonstrate the behaviour of each helper function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "567eb80b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from contextlib import contextmanager"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "156e7a8b",
   "metadata": {},
   "outputs": [],
   "source": [
    "@contextmanager\n",
    "def env(variable, value):\n",
    "    old = os.environ.get(variable, None)\n",
    "    try:\n",
    "        os.environ[variable] = value\n",
    "        yield\n",
    "    finally:\n",
    "        if old is None: del os.environ[variable]\n",
    "        else: os.environ[variable] = old"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec626e17",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def _path_from_env(variable, default):\n",
    "    value = os.environ.get(variable)\n",
    "    if value and os.path.isabs(value): return Path(value)\n",
    "    return default"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2231c39d",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def _paths_from_env(variable, default):\n",
    "    value = os.environ.get(variable)\n",
    "    if value:\n",
    "        paths = [Path(o) for o in value.split(\":\") if os.path.isabs(o)]\n",
    "        if paths: return paths\n",
    "    return default"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c57ecc16",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_cache_home():\n",
    "    \"Path corresponding to `XDG_CACHE_HOME`\"\n",
    "    return _path_from_env(\"XDG_CACHE_HOME\", Path.home()/\".cache\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d732690",
   "metadata": {},
   "outputs": [],
   "source": [
    "from fastcore.test import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad31affd",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_eq(xdg_cache_home(), Path.home()/'.cache')\n",
    "with env('XDG_CACHE_HOME', '/home/fastai/.cache'):\n",
    "    test_eq(xdg_cache_home(), Path('/home/fastai/.cache'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2b25813",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_config_dirs():\n",
    "    \"Paths corresponding to `XDG_CONFIG_DIRS`\"\n",
    "    return _paths_from_env(\"XDG_CONFIG_DIRS\", [Path(\"/etc/xdg\")])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10414109",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_eq(xdg_config_dirs(), [Path('/etc/xdg')])\n",
    "with env('XDG_CONFIG_DIRS', '/home/fastai/.xdg:/home/fastai/.config'):\n",
    "    test_eq(xdg_config_dirs(), [Path('/home/fastai/.xdg'), Path('/home/fastai/.config')])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5fb9fadd",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_config_home():\n",
    "    \"Path corresponding to `XDG_CONFIG_HOME`\"\n",
    "    return _path_from_env(\"XDG_CONFIG_HOME\", Path.home()/\".config\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b552f35b",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_eq(xdg_config_home(), Path.home()/'.config')\n",
    "with env('XDG_CONFIG_HOME', '/home/fastai/.config'):\n",
    "    test_eq(xdg_config_home(), Path('/home/fastai/.config'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4d26c69",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_data_dirs():\n",
    "    \"Paths corresponding to XDG_DATA_DIRS`\"\n",
    "    return _paths_from_env( \"XDG_DATA_DIRS\", [Path(o) for o in \"/usr/local/share/:/usr/share/\".split(\":\")])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d9c9c0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_data_home():\n",
    "    \"Path corresponding to `XDG_DATA_HOME`\"\n",
    "    return _path_from_env(\"XDG_DATA_HOME\", Path.home()/\".local\"/\"share\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b9b9897e",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_eq(xdg_data_home(), Path.home()/'.local/share')\n",
    "with env('XDG_DATA_HOME', '/home/fastai/.data'):\n",
    "    test_eq(xdg_data_home(), Path('/home/fastai/.data'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ded0956",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_runtime_dir():\n",
    "    \"Path corresponding to `XDG_RUNTIME_DIR`\"\n",
    "    value = os.getenv(\"XDG_RUNTIME_DIR\")\n",
    "    return Path(value) if value and os.path.isabs(value) else None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9025dca2",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "def xdg_state_home():\n",
    "    \"Path corresponding to `XDG_STATE_HOME`\"\n",
    "    return _path_from_env(\"XDG_STATE_HOME\", Path.home()/\".local\"/\"state\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b4f6a9f",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_eq(xdg_state_home(), Path.home()/'.local/state')\n",
    "with env('XDG_STATE_HOME', '/home/fastai/.state'):\n",
    "    test_eq(xdg_state_home(), Path('/home/fastai/.state'))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5eabac2f",
   "metadata": {},
   "source": [
    "## Export -"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91ca6dc2",
   "metadata": {},
   "outputs": [],
   "source": [
    "#|hide\n",
    "#|eval: false\n",
    "from nbdev import nbdev_export\n",
    "nbdev_export()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0818dd8b",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Copyright © 2016-2021 Scott Stevenson <scott@stevenson.io>\n",
    "\n",
    "Modifications copyright © 2022 onwards Jeremy Howard"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
